﻿using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using NHibernate;
using NHibernate.Criterion;
using Neturion.Dados;
using Neturion.IRepositorios;

namespace Neturion.Repositorios
{
    public class RepositorioCargo : IRepositorioCargo
    {
        public Cargo Inserir(Cargo cargo)
        {
            cargo.DataUltimoReajuste = cargo.DataUltimoReajuste.HasValue
                                            ? cargo.DataUltimoReajuste.GetValueOrDefault().Date
                                            : cargo.DataUltimoReajuste;
            cargo.FimVigencia = cargo.FimVigencia.HasValue
                                    ? cargo.FimVigencia.GetValueOrDefault().Date
                                    : cargo.FimVigencia;
            cargo.InicioVigencia = cargo.InicioVigencia.HasValue
                                        ? cargo.InicioVigencia.GetValueOrDefault().Date
                                        : cargo.InicioVigencia;

            GerenciadorBDConfigs.Instance.SessaoAtual().Save(cargo);
            return cargo;
        }

        public Cargo Atualizar(Cargo cargo)
        {
            Cargo tmpCargo = ObterPorId(cargo.CargoId);
            // Atribuicao dos valores do objeto da memoria para o objeto obtido no banco de dados
            tmpCargo.Cbo = cargo.Cbo;
            tmpCargo.Codigo = cargo.Codigo;
            tmpCargo.DataUltimoReajuste = tmpCargo.DataUltimoReajuste.HasValue
                                              ? tmpCargo.DataUltimoReajuste.GetValueOrDefault().Date
                                              : tmpCargo.DataUltimoReajuste;
            tmpCargo.Descricao = cargo.Descricao;
            tmpCargo.FimVigencia = cargo.FimVigencia.HasValue
                                    ? cargo.FimVigencia.GetValueOrDefault().Date
                                    : cargo.FimVigencia;
            tmpCargo.InicioVigencia = cargo.InicioVigencia.HasValue
                                        ? cargo.InicioVigencia.GetValueOrDefault().Date
                                        : cargo.InicioVigencia;
            tmpCargo.NeturionLog = cargo.NeturionLog;
            tmpCargo.Observacao = cargo.Observacao;
            tmpCargo.PercentualUltimoReajuste = cargo.PercentualUltimoReajuste;
            tmpCargo.PrevisaoSalarial = cargo.PrevisaoSalarial;
            tmpCargo.SalarioAnterior = cargo.SalarioAnterior;

            GerenciadorBDConfigs.Instance.SessaoAtual().Merge(tmpCargo);
            return tmpCargo;
        }

        public void Excluir(Cargo cargo)
        {
            GerenciadorBDConfigs.Instance.SessaoAtual().Delete(cargo);
        }

        public IList<Cargo> ObterTodos()
        {
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Cargo));
            return criteria.List<Cargo>() as List<Cargo>;
        }

        public Cargo ObterPorId(int id)
        {
            return GerenciadorBDConfigs.Instance.SessaoAtual().Get<Cargo>(id);
        }

        public IList<Cargo> ObterPorDescricao(int inicio, int quantidade, int quantidadeMinima, string descricao)
        {
            if (quantidade.Equals(0))
            {
                quantidade = quantidadeMinima;
            }

            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Cargo))
            .SetFirstResult(inicio).SetMaxResults(quantidade);
            criteria.Add(Restrictions.Like("Descricao", descricao, MatchMode.Anywhere));
            return criteria.List<Cargo>() as List<Cargo>;
        }

        public IList<Cargo> ObterPorCbo(int inicio, int quantidade, int quantidadeMinima, Cbo cbo)
        {
            if (quantidade.Equals(0))
            {
                quantidade = quantidadeMinima;
            }

            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Cargo))
            .SetFirstResult(inicio).SetMaxResults(quantidade);
            criteria.Add(Restrictions.Eq("Cbo", cbo));
            return criteria.List<Cargo>() as List<Cargo>;
        }


        public IList<Cargo> ObterPorDescricaoCbo(string descricaoCbo)
        {
            ICriteria criteria =
               GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Cargo))
               .CreateAlias("Cbo", "Cbo")
               .Add(Restrictions.Like("Cbo.Descricao", descricaoCbo, MatchMode.Anywhere));
            return criteria.List<Cargo>() as List<Cargo>;
        }

        public IList<Cargo> ObterTodos(int inicio, int quantidade, int quantidadeMinima, string codigo, string cboCodigo, string cboDescricao,
            string descricao, decimal previsaoSalarialDe, decimal previsaoSalarialAte, decimal salarioAnteriorDe, decimal salarioAnteriorAte, 
            decimal percentualUltimoReajusteDe, decimal percentualUltimoReajusteAte, DateTime? ultimoReajusteDe,
            DateTime? ultimoReajusteAte, DateTime? inicioVigenciaDe, DateTime? inicioVigenciaAte,
            DateTime? fimVigenciaDe, DateTime? fimVigenciaAte)
        {
            if (quantidade.Equals(0))
            {
                quantidade = quantidadeMinima;
            }

            IList<Cargo> list;
            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Cargo))
                
               .SetFirstResult(inicio).SetMaxResults(quantidade);

            if (!string.IsNullOrEmpty(codigo))
            {
                criteria.Add(Restrictions.Eq("Codigo", codigo));
            }

            if ( (!string.IsNullOrEmpty(cboCodigo)) || (!string.IsNullOrEmpty(cboDescricao)) )
            {
                criteria.CreateAlias("Cbo", "Cbo");
            }
            
            if (!string.IsNullOrEmpty(cboCodigo))
            {
                
               criteria.Add(Restrictions.Eq("Cbo.Codigo", cboCodigo));
            }

            if (!string.IsNullOrEmpty(cboDescricao))
            {
                
               criteria.Add(Restrictions.Like("Cbo.Descricao", cboDescricao, MatchMode.Anywhere));
            }

            if (!string.IsNullOrEmpty(descricao))
            {
                criteria.Add(Restrictions.Like("Descricao", descricao, MatchMode.Anywhere));
            }

            if (previsaoSalarialDe > 0)
            {
                criteria.Add(previsaoSalarialAte >= previsaoSalarialDe
                    ? Restrictions.Between("PrevisaoSalarial", previsaoSalarialDe, previsaoSalarialAte)
                    : Restrictions.Eq("PrevisaoSalarial", previsaoSalarialDe));
            }

            if (salarioAnteriorDe > 0)
            {
                criteria.Add(salarioAnteriorAte >= salarioAnteriorDe
                    ? Restrictions.Between("SalarioAnterior", salarioAnteriorDe, salarioAnteriorAte)
                    : Restrictions.Eq("SalarioAnterior", salarioAnteriorDe));
            }

            if (percentualUltimoReajusteDe > 0)
            {
                criteria.Add(percentualUltimoReajusteAte >= percentualUltimoReajusteDe
                    ? Restrictions.Between("PercentualUltimoReajuste", percentualUltimoReajusteDe, percentualUltimoReajusteAte)
                    : Restrictions.Eq("PercentualUltimoReajuste", percentualUltimoReajusteDe));
            }

            if (ultimoReajusteDe.HasValue)
            {
                criteria.Add(ultimoReajusteAte.HasValue
                    ? Restrictions.Between("DataUltimoReajuste", ultimoReajusteDe.Value.Date, ultimoReajusteAte.Value.Date)
                    : Restrictions.Eq("DataUltimoReajuste", ultimoReajusteDe.Value.Date));
            }

            if (inicioVigenciaDe.HasValue)
            {
                criteria.Add(inicioVigenciaAte.HasValue
                    ? Restrictions.Between("InicioVigencia", inicioVigenciaDe.Value.Date, inicioVigenciaAte.Value.Date)
                    : Restrictions.Eq("InicioVigencia", inicioVigenciaDe.Value.Date));
            }

            if (fimVigenciaDe.HasValue)
            {
                criteria.Add(fimVigenciaAte.HasValue
                    ? Restrictions.Between("FimVigencia", fimVigenciaDe.Value.Date, fimVigenciaAte.Value.Date)
                    : Restrictions.Eq("FimVigencia", fimVigenciaDe.Value.Date));
            }

            list = criteria.List<Cargo>() as List<Cargo>;

            //list = (from cnae in GerenciadorBDConfigs.Instance.SessaoAtual().Query<Cnae>()
            //        select cnae).Skip(inicio).Take(quantidade).ToList();

            return list;
        }

        public Cargo ObterPorCodigo(string codigo)
        {
            ICriteria criteria =
               GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof(Cargo)).Add(
                   Restrictions.Eq("Codigo", codigo));
            return criteria.UniqueResult<Cargo>();
        }

        public int ObterUltimoIdCodigoInteiro()
        {
            string[] literal = new string[] 
                {"a","b","c","d","e","f","g","h","i","j"
                ,"l","m","n","o","p","q","r","s","t","u","v","x","z","y"
                ,"w"};

            ICriteria criteria = GerenciadorBDConfigs.Instance.SessaoAtual().CreateCriteria(typeof (Cargo)).SetMaxResults(1);
            
            for (int i = 0; i <= literal.Length -1; i++)
            {
                criteria.Add(Restrictions.Not(Restrictions.Like("Codigo", literal[i], MatchMode.Anywhere)));
            }
           
            criteria.AddOrder(Order.Desc("CargoId"));
            

            Cargo cargo = criteria.UniqueResult<Cargo>();
            int ultimoCodigo = cargo != null ? cargo.CargoId : 0;

            return ultimoCodigo;
        }
    }
}